package com.glwan.fixedassetapp.ui.login;


import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.glwan.fixedassetapp.MainActivity;
import com.glwan.fixedassetapp.R;
import com.glwan.fixedassetapp.utils.CommonUtil;
import com.glwan.fixedassetapp.utils.DatabaseUtil;
import com.glwan.fixedassetapp.utils.MMKVKeys;
import com.glwan.fixedassetapp.utils.MMKVSingleton;
import com.glwan.fixedassetapp.utils.OkHttpUtil;
import com.glwan.fixedassetapp.utils.Sm2Util;
import com.google.gson.JsonObject;

import org.apache.commons.lang.StringUtils;
import org.bouncycastle.crypto.InvalidCipherTextException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


public class LoginActivity extends AppCompatActivity {

    private static final String TAG = "LoginActivity";
    /**
     * 获取公钥和cookie
     */
    private final String ENCRYPT_URI = "/resource/js/session.jsp";
    /**
     * 登录
     */
    private final String LOGIN_URI = "/j_acegi_security_check";
    TextView tvUsername;
    EditText etUsername;
    TextView tvPassword;
    EditText etPassword;
    EditText etServerAddress;
    DatabaseUtil databaseUtil;
    /**
     * 临时存储
     */
    private JsonObject jsonObjectTemp = new JsonObject();
    //登陆成功保存session
    Callback loginSessionCallback = new Callback() {
        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) {
            Log.d("onFailure: ", e.getMessage());
            CommonUtil.toastShow(getActivity(), "请求地址接口异常", CommonUtil.ERROR, true);
        }

        @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
            String body = response.body().string();
            Log.d(getClass().getName(), "body" + body);
            String[] sessions = body.split("SESSION:");
            if (sessions.length > 0) {
                String session = sessions[1].split(";")[0];
                Log.d(getClass().getName(), "session: " + session);
                MMKVSingleton.putString(MMKVKeys.KEY_SESSION, session);
                MMKVSingleton.putString(MMKVKeys.KEY_DOMAIN, jsonObjectTemp.get("domain").getAsString());
                jumpHomePage(1);
            }
        }
    };
    Callback encryptDataCallback = new Callback() {
        @Override
        public void onFailure(@NonNull Call call, @NonNull IOException e) {
            Log.d("onFailure: ", e.getMessage());
            CommonUtil.toastShow(getActivity(), "请求地址接口异常", CommonUtil.ERROR, true);

        }

        @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
            String body = response.body().string();
            // 处理字符串
            if (StringUtils.isEmpty(body) || !body.contains("getSessionId")) {
                CommonUtil.toastShow(getActivity(), "请求地址接口异常，获取不到key", CommonUtil.ERROR, true);
            }
            String[] splitBody = body.split("\"");
            String publicKey = splitBody[3];
            Log.d("publicKey ", splitBody[3]);
            //加密
            JsonObject encryptObject = encryptData(publicKey, jsonObjectTemp.get("userName").getAsString(), jsonObjectTemp.get("password").getAsString());
            Log.d(TAG, "encryptData " + encryptObject.toString());
            String encryptUserName = encryptObject.get("encryptUserName").getAsString();
            String encryptPwd = encryptObject.get("encryptPwd").getAsString();
            String domain = jsonObjectTemp.get("domain").getAsString();
            //登陆
            realLogin(domain, encryptUserName, encryptPwd);
        }

    };

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        databaseUtil = DatabaseUtil.getInstance(this);
        Log.i(TAG, "初始化database");
        TextView tvTitle = findViewById(R.id.tvTitle);
        tvTitle.setText(getString(R.string.login));
        tvUsername = findViewById(R.id.tvUsername);
        etUsername = findViewById(R.id.etUsername);
        tvPassword = findViewById(R.id.tvPassword);
        etPassword = findViewById(R.id.etPassword);
        etServerAddress = findViewById(R.id.etServerAddress);
        String domain = MMKVSingleton.getString(MMKVKeys.KEY_DOMAIN, "");
        if (!domain.isEmpty()) {
            etServerAddress.setText(domain);
        }
        Button bLogin = findViewById(R.id.bLogin);
        bLogin.setOnClickListener(view -> {
            if (StringUtils.isEmpty(etServerAddress.getText().toString())) {
                CommonUtil.toastShow(getActivity(), "address server is null", CommonUtil.ERROR, true);
            }
            if (StringUtils.isEmpty(etUsername.getText().toString()) || StringUtils.isEmpty(etPassword.getText().toString())) {
                CommonUtil.toastShow(getActivity(), "username or password is null", CommonUtil.ERROR, true);
            }

            login(etServerAddress.getText().toString(), etUsername.getText().toString(), etPassword.getText().toString());
        });

        Button bOfflineLogin = findViewById(R.id.bOfflineLogin);
        bOfflineLogin.setOnClickListener(view -> {

            jumpHomePage(0);
        });
    }

    /**
     * 登录（先加密）
     *
     * @param domain
     * @param userName
     * @param password
     */
    private void login(String domain, String userName, String password) {
        MMKVSingleton.putString(MMKVKeys.KEY_USERNAME, userName);
        encryptLogin(domain, userName, password);
    }

    /**
     * 加密数据
     *
     * @param publicKey
     * @param userName
     * @param password
     */
    private JsonObject encryptData(String publicKey, String userName, String password) {
        JsonObject jsonObject = new JsonObject();
        try {
            String encryptUserName = Sm2Util.enCrypt(userName, publicKey);
            String encryptPwd = Sm2Util.enCrypt(password, publicKey);
            jsonObject.addProperty("encryptUserName", encryptUserName);
            jsonObject.addProperty("encryptPwd", encryptPwd);
            return jsonObject;
        } catch (InvalidCipherTextException e) {
            throw new RuntimeException(e);
        }
    }

    private void encryptLogin(String domain, String userName, String password) {
        String encryptUrl = domain + ENCRYPT_URI;
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("userName", userName);
        jsonObject.addProperty("password", password);
        jsonObjectTemp.addProperty("userName", userName);
        jsonObjectTemp.addProperty("password", password);
        jsonObjectTemp.addProperty("domain", domain);
        OkHttpUtil.postNew(encryptUrl, "text/plain", new HashMap<>(), jsonObject, encryptDataCallback);
    }

    private void realLogin(String domain, String userName, String password) {
        String loginUrl = domain + LOGIN_URI;
        Map<String, List<Cookie>> cookieStore = new HashMap<>();
        OkHttpClient client = new OkHttpClient().newBuilder()
                .cookieJar(new CookieJar() {
                    @Override
                    public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
                        cookieStore.put(httpUrl.host(), list);
                    }

                    @Override
                    public List<Cookie> loadForRequest(HttpUrl httpUrl) {
                        List<Cookie> cookies = cookieStore.get(httpUrl.host());
                        return cookies != null ? cookies : new ArrayList<Cookie>();
                    }
                })
                .build();
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "j_username=" + userName + "&j_password=" + password);
        Request request = new Request.Builder()
                .url(loginUrl)
                .method("POST", body)
                .addHeader("Cookie", "")
                .build();
        client.newCall(request).enqueue(loginSessionCallback);
    }

    private void jumpHomePage(int menuType) {
        if (!canUse()) {
            return;
        }
        CommonUtil.openProgressDialog(getActivity(), getString(R.string.loading));

        Map<String, Object> map = new HashMap<>();
        //菜单类型: 1-在线版本, 0-离线版本
        map.put("menuType", menuType);
        CommonUtil.startActivity(getActivity(), MainActivity.class, map, true);
        CommonUtil.cancelProgressDialog(getActivity());
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
            return CommonUtil.exitApp(this);
        }
        return super.onKeyDown(keyCode, event);
    }

    private boolean canUse() {
        long l = 1714406400000L;    // 2024-04-30

        if (System.currentTimeMillis() > l) {
            CommonUtil.toastShow(getActivity(), "许可已过期", CommonUtil.ERROR, true);
            return false;
        }
        return true;
        // else
        //     log.info("许可有效期至：" + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(l)));
    }

    private Activity getActivity() {
        return LoginActivity.this;
    }


}
